﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DNEL.Extensions
{
    /// <summary>
    /// 
    /// </summary>
    public static class DateTimeExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetWeekOfYear(this DateTime dt)
        {
            // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
            // be the same week# as whatever Thursday, Friday or Saturday are,
            // and we always get those right
            DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(dt);
            if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday) dt = dt.AddDays(3);

            // Return the week of our adjusted day
            return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetDayOfYear(this DateTime dt)
        {
            return dt.DayOfYear;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsWeekend(this DateTime dt)
        {
            return dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsWeekday(this DateTime dt)
        {
            return !IsWeekend(dt);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsToday(this DateTime dt)
        {
            return dt.Date == DateTime.Today;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsEaster(this DateTime dt)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsChristman(this DateTime dt)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static bool IsPenteCost(this DateTime dt)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetAge(this DateTime dt)
        {
            if (DateTime.Today.Month < dt.Month ||
               (DateTime.Today.Month == dt.Month && DateTime.Today.Day < dt.Day))
            {
                return DateTime.Today.Year - dt.Year - 1;
            }
            else
            {
                return DateTime.Today.Year - dt.Year;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetNextDay(this DateTime dt)
        {
            return dt.AddDays(1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="Day"></param>
        /// <returns></returns>
        public static DateTime GetNextDay(this DateTime dt, DayOfWeek Day)
        {
            int diff = (int)dt.DayOfWeek - (int)Day;

            switch (diff)
            {
                case 0:
                    return dt;

                case -1:
                    return dt.AddDays(1);

                default:
                    return dt.AddDays(7 - diff);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="Zone"></param>
        /// <returns></returns>
        public static bool IsDaylightSavingTime(this DateTime dt, TimeZone Zone)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static TimeSpan UtcOffset(this DateTime dt)
        {
            return TimeZone.CurrentTimeZone.GetUtcOffset(dt);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="Date"></param>
        /// <returns></returns>
        public static bool IsBefore(this DateTime dt, DateTime Date)
        {
            return dt < Date;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="Date"></param>
        /// <returns></returns>
        public static bool IsAfter(this DateTime dt, DateTime Date)
        {
            return Date < dt;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="DateBefore"></param>
        /// <param name="DateAfter"></param>
        /// <returns></returns>
        public static bool IsBetween(this DateTime dt, DateTime DateBefore, DateTime DateAfter)
        {
            return dt.IsBefore(DateAfter) && dt.IsAfter(DateBefore);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DaylightTime GetDaylightTime(this DateTime dt)
        {
            return TimeZone.CurrentTimeZone.GetDaylightChanges(dt.Year);
        }
    }
}
